package com.tsd.wxpay.job;

import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.tsd.core.constants.Constants;
import com.tsd.core.datasource.DataSourceContextHolder;
import com.tsd.core.utils.ExceptionUtil;
import com.tsd.core.utils.HlpUtils;
import com.tsd.core.utils.ListUtil;
import com.tsd.core.job.JobBaseClass;
import com.tsd.wxpay.WxPayConfig4SysSettingService;
import com.tsd.wxpay.dao.WeixinPayNotifyLogMapper;
import com.tsd.wxpay.entity.WeixinPayNotifyLogExt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;

/**
 * @ClassName: WxPayQuartzJob
 * @Description: TODO
 * @Author: Hillpool
 * @Date: 2022/7/14 14:58
 * @Version: 1.0
 */
public abstract class WxPayQuartzJob extends JobBaseClass {

    public static final Logger LOGGER = LoggerFactory.getLogger(Constants.LOGGER_NAME_QUARTZ);

    private static final Integer PRE_RECONCILIATION_SIZE = 1;

    @Autowired
    protected WxPayService wxPayService;
    @Resource
    protected WxPayConfig4SysSettingService wxPayConfig4SysSettingService;
    @Resource
    protected WeixinPayNotifyLogMapper weixinPayNotifyLogMapper;

    protected void startReconciliation() {
        LOGGER.info("执行账单对账，账套：{}", DataSourceContextHolder.getDataSourceType());
        try {
            WxPayConfig config = wxPayConfig4SysSettingService.getWxPayConfig(null);
            Long greaterThanId = null;
            while (true) {
                List<WeixinPayNotifyLogExt> list = weixinPayNotifyLogMapper.selectValid4Reconciliation(greaterThanId, PRE_RECONCILIATION_SIZE);
                if (HlpUtils.isEmptyList(list)) {
                    break;
                }
                for (WeixinPayNotifyLogExt logExt : list) {
                    this.doOneReconciliation(logExt, config);
                }
                WeixinPayNotifyLogExt max = ListUtil.max(list, Comparator.comparing(WeixinPayNotifyLogExt::getId));
                if (max != null) {
                    greaterThanId = max.getId();
                }
                if (list.size() < PRE_RECONCILIATION_SIZE) {
                    break;
                }
            }
        } catch (Exception e) {
            LOGGER.error(ExceptionUtil.getStackTraceFromException(e));
        }
    }

    private void doOneReconciliation(WeixinPayNotifyLogExt logExt, WxPayConfig config) {
        if (HlpUtils.isEmpty(logExt.getHook_update())) {
            logExt.setHook_update(0);
        }
        try {
            config.setAppId(logExt.getApp_id());
            wxPayService.setConfig(config);

            WxPayOrderQueryResult result = wxPayService.queryOrder(null, logExt.getOut_trade_no());
            if (WxPayConstants.WxpayTradeStatus.NOTPAY.equals(result.getTradeState())) {
                return;
            }
            if (WxPayConstants.WxpayTradeStatus.SUCCESS.equals(result.getTradeState()) || WxPayConstants.WxpayTradeStatus.REFUND.equals(result.getTradeState())) {
                this.procPaySuccess(logExt);
            }
            logExt.update(result);
        } catch (WxPayException e) {
            logExt.setReturn_code(e.getReturnCode());
            logExt.setReturn_msg(e.getReturnMsg());
            logExt.setResult_code(e.getResultCode());
            logExt.setErr_code(e.getErrCode());
            logExt.setErr_code_des(e.getErrCodeDes());
        } catch (Exception e) {
            LOGGER.error(ExceptionUtil.getStackTraceFromException(e));
        }
        logExt.setIs_reconciliation(1);
        weixinPayNotifyLogMapper.updateByPrimaryKey(logExt);
    }

    public abstract void procPaySuccess(WeixinPayNotifyLogExt logExt);
}
